package acewem.gui;

import java.util.Enumeration;

import javax.swing.JFrame;

import acewem.market.ACEWEMmodel;
import acewem.market.GenCo;
import acewem.utilities.statistics.graphics.MultiTimeSeriesChartGenerator;

import sim.display.Console;
import sim.display.Controller;
import sim.display.GUIState;
import sim.engine.SimState;
import sim.engine.Steppable;
import sim.portrayal.Inspector;

import acewem.utilities.optimisation.OptimalPowerFlow;

/**
 * 
 * @author 
 *
 */
public class ACEWEMGUI extends GUIState 
{
	
	private ACEWEMmodel market;
	private GUIReporter guiReporter;
	private OptimalPowerFlow opf;
	
	

	/**
	 * 
	 * @param state
	 */
	public ACEWEMGUI(SimState state) 
	{
		super(state);
		market=(ACEWEMmodel)state;
		this.guiReporter=new GUIReporter(market);
		opf = new OptimalPowerFlow(market);
	}

	/**
     * this is the first method that is executed once the start button is pressed
     */
	public void start() 
	{
		super.start();
		this.updater();
		//this.scheduleRepeatingImmediatelyAfter(this.guiReporter);
	}
	
  /**
  * 
  * 	
  */
  private void updater()
  {
	final Steppable updater = new Steppable()
	{	
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		public void step(SimState simState) 
		{

			GenCo gen  = null;
	        Enumeration<String> e = market.genCoList.keys();
			int step=(int)market.schedule.getSteps();
			//System.out.println(market.schedule.getSteps());
		//	System.out.println(step);
			
			
			
			
	        while(e.hasMoreElements())
	        {
	        	gen = market.genCoList.get(e.nextElement());
	        	//update learning
	        	gen.learn();
	        	
	        	//update graphics Supply offer
	        	gen.reportedSupplyOfferB.add(step,gen.getbR());
		        gen.reportedSupplyOfferA.add(step,gen.getaR());
		        gen.trueSupplyOfferB.add(step,gen.getbT());
		        gen.trueSupplyOfferA.add(step,gen.getaT());
		        
		    	//update graphics GenCo commitment hourly
/*				for (int h=0; h<market.Hours; h++)
		    	{
		    		if(step==422)
		    		{
		            gen.commitmentA.add(h,gen.getcommitment(h));
		            System.out.println(gen.getID()+ ": " + h + " com:"+ gen.getcommitment(h));
		    		}		                        
		        }		     
 */
		        
		       //update graphics Node LMP's cummulative daily
	        	gen.cumulativelmp.add(step,gen.getlmpCummulative());
		        
			}	
			//market.makeGenCoLearn();
		}
		
	};
	this.scheduleRepeatingImmediatelyAfter(updater);
   }
  
  /** this gives the 'model' tab in the consol of the GUI */
  public Object getSimulationInspectedObject()
  {
  	return state;
  }
  

  public void finish()
  {
  	super.finish();
  	this.resetModelParameters();
  }
  
  public void resetModelParameters()
  {
	this.market.resetModelParameters();	
  }
  
  /**
   * Since the GUIState needs to know when the GUI has been lanched
   * the init method is used to register the visualisations
   * using the c.registerFrame function
   * */
   
  public void init (Controller c)
  {
  	super.init(c);
  	//add more here
  //	this.prepareRSupplyGraphics(c);
  //	this.prepareGenCoCommitmentGraphics(c);
  	
  	
  	
	   GenCo gen  = null;
       Enumeration<String> e = market.genCoList.keys();
      // if (e == null){return;}
     
    
//====================================================================================================	     

    	 while(e.hasMoreElements())
     	 {
    		 gen = market.genCoList.get(e.nextElement());
    		 gen.submitTrueSupplyOffer();
    		}
    		// iso.step(this);
    		// gen.lmpCummulativeTrue 	  = gen.lmpCummulative;
    		// gen.commitmentCumulativeTrue = gen.commitmentCumulative;
    		opf.solveHourlyPowerFlows1();
    		

    		//	 gen.updateDailyPerformance();
    		updategencos();
   
    	// 	market.iso.step(market);
    	
    	//	 gen.lmpCummulativeTrue 	  = gen.lmpCummulative;
    	//	 gen.commitmentCumulativeTrue = gen.commitmentCumulative;
   

 		this.prepareCumulativeLMPGraphics(c);
    	 
  }
  
  public void updategencos(){
	  
	   GenCo gen  = null;
       Enumeration<String> e = market.genCoList.keys();
  	 while(e.hasMoreElements())
 	 {
		 gen = market.genCoList.get(e.nextElement());
		 gen.updateDailyPerformance();}
	    }
  
  
  
  
  
  private void prepareRSupplyGraphics(Controller c) 
  {
		GenCo gen  = null;
   	    MultiTimeSeriesChartGenerator genCoTS=null;
   	    JFrame genCoFrame=null;
        Enumeration<String> e = this.market.genCoList.keys();
        //if (e == null){return;}
        while(e.hasMoreElements())
        {
        	gen = this.market.genCoList.get(e.nextElement());
        	genCoTS= new MultiTimeSeriesChartGenerator();
        	genCoTS.setTitle(gen.getID()+ ": trueA=" + gen.getaT() + " & trueB=" + gen.getbT());
        	genCoTS.setXAxisLabel("Simulated day");
        	//genCoTS.addSeries(gen.trueSupplyOfferA,null,0);
        	genCoTS.addSeries(gen.reportedSupplyOfferA,null,0);
        	//genCoTS.addSeries(gen.trueSupplyOfferB,null,1);
        	genCoTS.addSeries(gen.reportedSupplyOfferB,null,1);
        	genCoFrame= genCoTS.createFrame(this);
        	genCoFrame.setVisible(true);	
        	c.registerFrame(genCoFrame);  	
        }      
        
  }
  
  
  private void prepareGenCoCommitmentGraphics(Controller c) 
  {
		GenCo gen  = null;
   	    MultiTimeSeriesChartGenerator genCoTS=null;
   	    JFrame genCoFrame=null;
        Enumeration<String> e = this.market.genCoList.keys();
        //if (e == null){return;}
        while(e.hasMoreElements())
        {
        	gen = this.market.genCoList.get(e.nextElement());
        	genCoTS= new MultiTimeSeriesChartGenerator();
        		
        		genCoTS.setTitle(gen.getID());  		
        		genCoTS.setXAxisLabel("Hours");
        		genCoTS.addSeries(gen.commitmentA,null,0);
        		genCoFrame= genCoTS.createFrame(this);
        		genCoFrame.setVisible(true);	
        		c.registerFrame(genCoFrame); 

        }      
        
  }
  
  private void prepareCumulativeLMPGraphics(Controller c) 
  {
		GenCo gen  = null;
 	    MultiTimeSeriesChartGenerator genCoTS=null;
 	    JFrame genCoFrame=null;
      Enumeration<String> e = this.market.genCoList.keys();
      //if (e == null){return;}
      while(e.hasMoreElements())
      {
      	gen = this.market.genCoList.get(e.nextElement());
      	genCoTS= new MultiTimeSeriesChartGenerator();

      	genCoTS.setTitle("Node at GenCo"+gen.getID()+ ": Cumulative daily LMP with no GenCo learning= " + gen.lmpCummulative);                    

      	genCoTS.setXAxisLabel("Simulated day");
      	//genCoTS.addSeries(gen.trueSupplyOfferA,null,0);
      	genCoTS.addSeries(gen.cumulativelmp,null,0);
      	//genCoTS.addSeries(gen.trueSupplyOfferB,null,1);
 //     	genCoTS.addSeries(gen.reportedSupplyOfferB,null,1);
      	genCoFrame= genCoTS.createFrame(this);
      	genCoFrame.setVisible(true);	
      	c.registerFrame(genCoFrame);  	
      }      
      
}
  
  
  
  
  public static String getName() 
  { 
	  return "ACEWEM for Wholesale Electricity Markets"; 
  }

  	public void quit() 
	{
		super.quit();
		System.exit(0);
	}
  
  	public Inspector getInspector()
	{
		Inspector i = super.getInspector(); 
		i.setVolatile(true); 
		return i; 
	}
  
    //To load 'serializable' states - Fix it!
	public void load(SimState state) 
	{
		super.load(state);		
	}
	
	public static Object getInfo()
	{
		return
		"<H1> <CENTER>  The ACEWEM Project</CENTER></H1>"+
		"<CENTER>Agent-based Computational Economics of the Wholesale Electricity Market</CENTER>"+
		"<br>The ACEWEM framework is an agent-based computational laboratory designed for the systematic study of the UK restructured wholesale electricity market operating over AC transmission grid subject to congestion. In the ACEWEM framework, electricity traders have learning capabilities permitting them to evolve their trading strategies over time. " +
		"<br><br>Our longer-run goal for the ACEWEM framework is a computational laboratory that rings true to industry participants and policy makers and that can be used as a research and training tool for long-term planning and investment processes in the wholesale electricity markets."+
		"<p><b>Authors:</b> Daniil Kiose & Dr. Vlasios Voudouris</p>"+
		"<br><b><CENTER> Centre for International Business and Sustainability (CIBS)</CENTER></b>"+
		"<b><CENTER> London Metropolitan Business School (LMBS)</CENTER></b>";
	}

	/**
	 * 
	 * @param args
	*/
	public static void main(String[] args)
	{	 
	 ACEWEMmodel market = new ACEWEMmodel(System.currentTimeMillis(), true);  
	 ACEWEMGUI gui =new ACEWEMGUI(market);
	 Console c = new Console(gui);
	 c.setBounds(600, 5,500, 450);
	 c.setVisible(true);
     market.finish();
	}

}
